#include "stdafx.h"
#include "LineFlowButton.h"

#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if (p) { delete (p); (p) = 0; } }
#endif // SAFE_DELETE

IMPLEMENT_DUICONTROL(CLineFlowButtonUI)
/////////////////////////////////////////////////////////////////////////////////////
//
//
#define  MAX_GRADIENT_LENGTH_INT 200
#define  MAX_GRADIENT_LENGTH_FLOAT (200.0)


CLineFlowButtonUI::CLineFlowButtonUI()
	: CButtonUI(),
	m_sBkTextureImage(_T("")),
	m_sFgTextureImage(_T(""))
{
	m_nDrawSpeed = 5;
	m_ePaintDirection = PaintDiretion_Num;

	Reset();
	m_bSolidity = false;
	m_nForeAnimaTimerDuration = 100;
	m_nSpeedLength = 100;

	m_pPreLink = NULL;
	m_pNextLink = NULL;

	m_eFlowLinkStatus = FLOW_LINK_START;
	m_eEndPointType = END_POINT_TYPE_NONE;
}

CLineFlowButtonUI::~CLineFlowButtonUI()
{
}


void CLineFlowButtonUI::Reset()
{
	m_bIsOnce = false;
	m_ePaintMode = PaintMode_Num;
	m_ePaintType = PaintType_Num;
}

void CLineFlowButtonUI::SetBkTextureImage(LPCTSTR pStrImage)
{
	m_sBkTextureImage = pStrImage;
	Invalidate();
}

LPCTSTR CLineFlowButtonUI::GetBkTextureImage()
{
	return m_sBkTextureImage;
}

void CLineFlowButtonUI::SetFgTextureImage(LPCTSTR pStrImage)
{
	m_sFgTextureImage = pStrImage;
	Invalidate();
}

LPCTSTR CLineFlowButtonUI::GetFgTextureImage()
{
	return m_sFgTextureImage;
}



void CLineFlowButtonUI::SetDrawDirection(LPCTSTR pStrDirection)
{
	if (_tcsicmp(pStrDirection, _T("left2right")) == 0) {
		m_ePaintDirection = PaintDiretion_Left2Right;
	}
	else if (_tcsicmp(pStrDirection, _T("right2left")) == 0) {
		m_ePaintDirection = PaintDiretion_Right2Left;
	}
	else if (_tcsicmp(pStrDirection, _T("bottom2top")) == 0) {
		m_ePaintDirection = PaintDiretion_Bottom2Top;
	}
	else if (_tcsicmp(pStrDirection, _T("top2bottom")) == 0) {
		m_ePaintDirection = PaintDiretion_Top2Bottom;
	}
	else {
		return;
	}

	Invalidate();
}

LPCTSTR CLineFlowButtonUI::GetDrawDirection()
{
	return m_sDrawDirection;
}

void CLineFlowButtonUI::SetEndPointType(LPCTSTR endPointType)
{
	if (_tcsicmp(endPointType, _T("leftup")) == 0) {
		m_eEndPointType = END_POINT_LEFT_UP;
	}
	else if (_tcsicmp(endPointType, _T("rightup")) == 0) {
		m_eEndPointType = END_POINT_RIGHT_UP;
	}
	else if (_tcsicmp(endPointType, _T("leftdown")) == 0) {
		m_eEndPointType = END_POINT_LEFT_DOWN;
	}
	else if (_tcsicmp(endPointType, _T("rightdown")) == 0) {
		m_eEndPointType = END_POINT_RIGHT_DOWN;
	}
	else {
		return;
	}

	Invalidate();
}

CLineFlowButtonUI::END_POINT_TYPE CLineFlowButtonUI::GetEndPointType()
{
	return m_eEndPointType;
}

void CLineFlowButtonUI::SetBgLineColor(DWORD dwColor)
{
	m_sBgLineColor = dwColor;
	Invalidate();
}

DWORD CLineFlowButtonUI::GetBgLineColor()
{
	return m_sBgLineColor;
}

void CLineFlowButtonUI::SetFgLineColor(DWORD dwColor)
{
	m_sFgLineColor = dwColor;
	Invalidate();
}

DWORD CLineFlowButtonUI::GetFgLineColor()
{
	return m_sFgLineColor;
}

bool CLineFlowButtonUI::IsSolidity() const {
	return m_bSolidity;
}

void CLineFlowButtonUI::SetSolidity(bool bSolidity) {
	m_bSolidity = bSolidity;
}

INT CLineFlowButtonUI::GetSpeedLength() const
{
	return m_nSpeedLength;
}

void CLineFlowButtonUI::SetSpeedLength(int speed)
{
	m_nSpeedLength = speed;
}

CLineFlowButtonUI* CLineFlowButtonUI::GetPreLink() const {
	return m_pPreLink;
}

void CLineFlowButtonUI::SetPreLink(LPCTSTR pstrValue) {
	//m_pPreLink = static_cast<CLineFlowButtonUI*>(m_pManager->FindControl(pstrValue));
	m_sPreLink = pstrValue;
}

CLineFlowButtonUI* CLineFlowButtonUI::GetNextLink() const {
	return m_pNextLink;
}

void CLineFlowButtonUI::SetNextLink(LPCTSTR pstrValue) {
	//m_pNextLink = static_cast<CLineFlowButtonUI*>(m_pManager->FindControl(pstrValue));
	m_sNextLink = pstrValue;
}

void CLineFlowButtonUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
{
	if (_tcsicmp(pstrName, _T("bktexture")) == 0) SetBkTextureImage(pstrValue);
	if (_tcsicmp(pstrName, _T("fgtexture")) == 0) SetFgTextureImage(pstrValue);
	else if (_tcsicmp(pstrName, _T("drawdirection")) == 0) SetDrawDirection(pstrValue);
	else if (_tcsicmp(pstrName, _T("endtype")) == 0) SetEndPointType(pstrValue);
	else if (_tcsicmp(pstrName, _T("bglinecolor")) == 0) {
		while (*pstrValue > _T('\0') && *pstrValue <= _T(' ')) pstrValue = ::CharNext(pstrValue);
		if (*pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
		LPTSTR pstr = NULL;
		DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
		SetBgLineColor(clrColor);
	}
	else if (_tcsicmp(pstrName, _T("fglinecolor")) == 0) {
		while (*pstrValue > _T('\0') && *pstrValue <= _T(' ')) pstrValue = ::CharNext(pstrValue);
		if (*pstrValue == _T('#')) pstrValue = ::CharNext(pstrValue);
		LPTSTR pstr = NULL;
		DWORD clrColor = _tcstoul(pstrValue, &pstr, 16);
		SetFgLineColor(clrColor);
	}
	else if (_tcsicmp(pstrName, _T("fglinesolidity")) == 0) SetSolidity(_tcsicmp(pstrValue, _T("true")) == 0);
	else if (_tcsicmp(pstrName, _T("speedpertime")) == 0) SetSpeedLength(_ttoi(pstrValue));
	else if (_tcsicmp(pstrName, _T("prelink")) == 0) SetPreLink(pstrValue);
	else if (_tcsicmp(pstrName, _T("nextlink")) == 0) SetNextLink(pstrValue);
	else CButtonUI::SetAttribute(pstrName, pstrValue);
}

void CLineFlowButtonUI::PaintBkImage(HDC hDC) {

	Gdiplus::Brush *pBrush = NULL;
	if (IsSolidity()) {
		pBrush = new Gdiplus::SolidBrush(GetBgLineColor());
	}
	else {
		Gdiplus::LinearGradientBrush *lnBrush;
		Gdiplus::Color cs[] = {
			GetBgLineColor(),
			Gdiplus::Color::White,
			GetBgLineColor()
		};
		Gdiplus::REAL  bs[] = {
			0,
			0.5,
			1
		};

		switch (m_ePaintDirection) {
		case PaintDiretion_Left2Right:
		case PaintDiretion_Right2Left:
			lnBrush = new Gdiplus::LinearGradientBrush(Gdiplus::Point(0, m_rcItem.top - 2), Gdiplus::Point(0, m_rcItem.top + GetHeight() + 2), GetBgLineColor(), GetBgLineColor());
			break;
		case PaintDiretion_Bottom2Top:
		case PaintDiretion_Top2Bottom:
			lnBrush = new Gdiplus::LinearGradientBrush(Gdiplus::Point(m_rcItem.left - 2, 0), Gdiplus::Point(m_rcItem.left + GetWidth() + 2, 0), GetBgLineColor(), GetBgLineColor());
			break;
		default:
			lnBrush = new Gdiplus::LinearGradientBrush(Gdiplus::Point(0, m_rcItem.top - 2), Gdiplus::Point(0, m_rcItem.top + GetHeight() + 2), GetBgLineColor(), GetBgLineColor());
			break;
		}
		lnBrush->SetInterpolationColors(cs, bs, 3);
		pBrush = lnBrush;
	}

	Gdiplus::Graphics graphics(hDC);
	graphics.FillRectangle(pBrush, GetPos().left, GetPos().top, GetWidth(), GetHeight());
	delete pBrush;
}

void CLineFlowButtonUI::GradientFgPaint(HDC hDC, FLOAT mid) {

	Gdiplus::LinearGradientBrush *lnBrush;
	Gdiplus::Color cs[] = {
		GetFgLineColor(),
		Gdiplus::Color::White,
		GetFgLineColor()
	};
	Gdiplus::REAL  bs[] = {
		0,
		mid,
		1
	};

#define GRADIENT_EXT_LENGTH 100
	Gdiplus::Graphics graphics(hDC);
	switch (m_ePaintDirection) {
	case PaintDiretion_Left2Right:
		lnBrush = new Gdiplus::LinearGradientBrush(Gdiplus::Point(m_rcItem.left - 2, 0), Gdiplus::Point(m_rcItem.left + GetWidth() + 2 + GRADIENT_EXT_LENGTH, 0), GetBgLineColor(), GetBgLineColor());
		lnBrush->SetInterpolationColors(cs, bs, 3);
		graphics.FillRectangle(lnBrush, GetPos().left + 1, GetPos().top + 1, GetWidth() - 2, GetHeight() - 2);
		break;
	case PaintDiretion_Right2Left:
		lnBrush = new Gdiplus::LinearGradientBrush(Gdiplus::Point(m_rcItem.left + GetWidth() + 2, 0), Gdiplus::Point(m_rcItem.left - 2 - GRADIENT_EXT_LENGTH, 0), GetBgLineColor(), GetBgLineColor());
		lnBrush->SetInterpolationColors(cs, bs, 3);
		graphics.FillRectangle(lnBrush, GetPos().left + 1, GetPos().top + 1, GetWidth() - 2, GetHeight() - 2);
		break;
	case PaintDiretion_Bottom2Top:
		lnBrush = new Gdiplus::LinearGradientBrush(Gdiplus::Point(0, m_rcItem.top + GetHeight() + 2), Gdiplus::Point(0, m_rcItem.top - 2 - GRADIENT_EXT_LENGTH), GetBgLineColor(), GetBgLineColor());
		lnBrush->SetInterpolationColors(cs, bs, 3);
		graphics.FillRectangle(lnBrush, GetPos().left + 1, GetPos().top + 1, GetWidth() - 2, GetHeight() - 2);
		break;
	case PaintDiretion_Top2Bottom:
		lnBrush = new Gdiplus::LinearGradientBrush(Gdiplus::Point(0, m_rcItem.top - 2), Gdiplus::Point(0, m_rcItem.top + GetHeight() + 2 + GRADIENT_EXT_LENGTH), GetBgLineColor(), GetBgLineColor());
		lnBrush->SetInterpolationColors(cs, bs, 3);
		graphics.FillRectangle(lnBrush, GetPos().left + 1, GetPos().top + 1, GetWidth() - 2, GetHeight() - 2);
		break;
	default:
		lnBrush = new Gdiplus::LinearGradientBrush(Gdiplus::Point(0, m_rcItem.top - 2), Gdiplus::Point(0, m_rcItem.top + GetHeight() + 2 + GRADIENT_EXT_LENGTH), GetBgLineColor(), GetBgLineColor());
		lnBrush->SetInterpolationColors(cs, bs, 3);
		graphics.FillRectangle(lnBrush, GetPos().left + 1, GetPos().top + 1, GetWidth() - 2, GetHeight() - 2);
		break;
	}
}

void CLineFlowButtonUI::GradientFgPaint_1(HDC hDC, FLOAT mid) {
	Gdiplus::Graphics graphics(hDC);
	Gdiplus::Pen	pen(Gdiplus::Color(GetFgLineColor()), getPenSize() - 2);
	//pen.SetStartCap(Gdiplus::LineCapRound);
	//pen.SetEndCap(Gdiplus::LineCapRound);
	//graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy);

	//Gdiplus::Brush *pBrush = new Gdiplus::SolidBrush(0xffffffff/*GetFgLineColor()*/);
	//graphics.FillPie(pBrush, GetPos().right - 2*GetHeight(), GetPos().top, 20, 20, 270, 90);

	Gdiplus::Brush *pBrush = new Gdiplus::SolidBrush(GetFgLineColor());
	switch (m_ePaintDirection) {
	case PaintDiretion_Left2Right:
	case PaintDiretion_Right2Left:
		switch (m_eEndPointType) {
		case END_POINT_LEFT_UP:
			if (m_ePaintDirection == PaintDiretion_Left2Right) {
				graphics.DrawLine(&pen, m_startx + GetHeight(), m_starty, m_endx, m_endy);
				graphics.FillPie(pBrush, GetPos().left, GetPos().top, 2 * GetHeight(), 2 * GetHeight(), 180, 90);
			}
			else {
				graphics.DrawLine(&pen, m_startx , m_starty, m_endx + GetHeight(), m_endy);
				graphics.FillPie(pBrush, GetPos().left, GetPos().top, 2 * GetHeight(), 2 * GetHeight(), 180, 90);
			}
			break;
		case END_POINT_RIGHT_UP:
			graphics.DrawLine(&pen, m_startx, m_starty, m_endx - GetHeight(), m_endy);
			graphics.FillPie(pBrush, GetPos().right - 2 * GetHeight(), GetPos().top, 2 * GetHeight(), 2 * GetHeight(), 270, 90);
			break;
		case END_POINT_LEFT_DOWN:
			graphics.DrawLine(&pen, m_startx, m_starty, m_endx+GetHeight(), m_endy);
			graphics.FillPie(pBrush, GetPos().left, GetPos().top- GetHeight(), 2 * GetHeight(), 2 * GetHeight(), 90, 90);
			break;
		case END_POINT_RIGHT_DOWN:
			graphics.DrawLine(&pen, m_startx, m_starty, m_endx - GetHeight(), m_endy);
			graphics.FillPie(pBrush, GetPos().right- 2 * GetHeight(), GetPos().top - GetHeight(), 2 * GetHeight(), 2 * GetHeight(), 0, 90);
			break;
		default:
			graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy);
			break;
		}
		break;

	case PaintDiretion_Bottom2Top:
	case PaintDiretion_Top2Bottom:
		switch (m_eEndPointType) {
		case END_POINT_LEFT_UP:
			if (m_ePaintDirection == PaintDiretion_Top2Bottom) {
				graphics.DrawLine(&pen, m_startx, m_starty + GetWidth(), m_endx, m_endy);
				graphics.FillPie(pBrush, GetPos().left, GetPos().top, 2 * GetWidth(), 2 * GetWidth(), 180, 90);
			}
			else {
				graphics.DrawLine(&pen, m_startx, m_starty , m_endx, m_endy + GetWidth());
				graphics.FillPie(pBrush, GetPos().left, GetPos().top, 2 * GetWidth(), 2 * GetWidth(), 180, 90);
			}		
			break;
		case END_POINT_RIGHT_UP:
			graphics.DrawLine(&pen, m_startx, m_starty , m_endx, m_endy + GetWidth());
			graphics.FillPie(pBrush, GetPos().right - 2 * GetWidth(), GetPos().top, 2 * GetWidth(), 2 * GetWidth(), 270, 90);
			break;
		case END_POINT_LEFT_DOWN:
			graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy - GetWidth());
			graphics.FillPie(pBrush, GetPos().left, GetPos().bottom - 2* GetWidth(), 2 * GetWidth(), 2 * GetWidth(), 90, 90);
			break;
		case END_POINT_RIGHT_DOWN:
			graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy - GetWidth());
			graphics.FillPie(pBrush, GetPos().left - GetWidth(), GetPos().bottom - 2*GetWidth(), 2 * GetWidth(), 2 * GetWidth(), 0, 90);
			break;
		default:
			graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy);
			break;
		}
		break;

	default:
		break;
	}

	DWORD	color1 = DWORD(0x10b3f3ef /** mid*//*(rand() % 11 / 11.0)*/);
	DWORD	color2 = color1/*DWORD(0x50e0e2b6 * (rand() % 11 / 11.0))*/;
	BOOL	bVertical = false;
	RECT rcItem = {};
	switch (m_ePaintDirection) {
	case PaintDiretion_Left2Right:
		bVertical = false;
		rcItem = { GetPos().left + INT(GetWidth() * mid) , GetPos().top, GetPos().left + INT(GetWidth() * mid) + GetWidth()/2, GetPos().bottom };
		break;
	case PaintDiretion_Right2Left:
		bVertical = false;
		rcItem = { GetPos().left + INT(GetWidth() * (1.0 - mid)), GetPos().top,GetPos().left + INT(GetWidth() * (1.0 - mid)) + GetWidth() / 2 , GetPos().bottom };
		CRenderEngine::DrawGradient(hDC, rcItem, color1, color2, bVertical, 1);
		break;
	case PaintDiretion_Bottom2Top:
		bVertical = true;
		rcItem = { GetPos().left, GetPos().top + INT(GetHeight() * (1.0 - mid)),  GetPos().right,   GetPos().top + INT(GetHeight() * (1.0 - mid) + GetHeight() / 2) };
		CRenderEngine::DrawGradient(hDC, rcItem, color1, color2, bVertical, 1);
		break;
	case PaintDiretion_Top2Bottom:
		bVertical = true;
		rcItem = { GetPos().left, GetPos().top + INT(GetHeight() * (mid)) , GetPos().right,   GetPos().top + INT(GetHeight() * (mid)) + GetHeight() / 2 };
		CRenderEngine::DrawGradient(hDC, rcItem, color1, color2, bVertical, 1);
		break;
	default:
		break;
	}
	//CRenderEngine::DrawImageString(hDC, m_pManager, rcItem, m_rcPaint, GetFgTextureImage(), NULL, m_instance);
	CRenderEngine::DrawGradient(hDC, rcItem, color1, color2, bVertical, 1);
}

bool CLineFlowButtonUI::DoPaint(HDC hDC, const RECT& rcPaint, CControlUI* pStopControl)
{
	if (!::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem)) return true;

	__super::DoPaint(hDC, rcPaint, pStopControl);

	if (m_ePaintType == PaintType_Line) {
		if (m_ePaintMode == PaintMode_Static) {
			PaintLine(hDC);
		}
		else if (m_ePaintMode == PaintMode_StaticFlicker) {
			PaintLineFlicker(hDC);
		}
		else if (m_ePaintMode == PaintMode_SegPad) {
			PaintLineSeg(hDC);
		}
		else if (m_ePaintMode == PaintMode_Flicker) {
			PaintLineFlicker(hDC);
		}
		else if (m_ePaintMode == PaintMode_Flow) {
			//PaintLineFlow(hDC);
			PaintGradientFlow(hDC);
		}
	}
	else if (m_ePaintType == PaintType_Texture) {
		if (m_ePaintMode == PaintMode_Static) {
			PaintWithTexture(hDC);
		}
		else if (m_ePaintMode == PaintMode_StaticFlicker) {
			PaintFlickerWithTexture(hDC);
		}
		else  if (m_ePaintMode == PaintMode_SegPad) {
			PaintLineSegWithTexture(hDC);
		}
		else if (m_ePaintMode == PaintMode_Flicker) {
			PaintFlickerWithTexture(hDC);
		}
		else if (m_ePaintMode == PaintMode_Flow) {
			PaintFlowWithTexture(hDC);
		}
	}

	return true;
}

void CLineFlowButtonUI::DoEvent(TEventUI& event)
{
	CButtonUI::DoEvent(event);

	if (event.Type == UIEVENT_TIMER)
	{
		OnTimer((UINT_PTR)event.wParam);
	}
}

void CLineFlowButtonUI::OnTimer(UINT_PTR idEvent)
{
	if (idEvent != EVENT_ANIMA_FLOW_FLOW_TIMERID)
		return;

	m_pManager->KillTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID);
	this->Invalidate();

	if (m_ePaintMode == PaintMode_SegPad || m_ePaintMode == PaintMode_Flicker) {
		if (m_ePaintType == PaintType_Line) {
			updateDrawInfo_Line();
		}
		else if (m_ePaintType == PaintType_Texture) {
			updateDrawInfo_Texture();
		}
		m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
	}
	else if (m_ePaintMode == PaintMode_Flow) {
		m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, FLOW_FLOW_TIMERID_DURATION);
	}
	else {

	}
}

void CLineFlowButtonUI::DoInit()
{
	LPCTSTR  bkImageName = GetBkTextureImage();
	LPCTSTR  fgImageName = GetFgTextureImage();

	m_pTextureBrush_bk = new Gdiplus::TextureBrush(CRenderEngine::GdiplusLoadImage(bkImageName));
	m_pTextureBrush_fg = new Gdiplus::TextureBrush(CRenderEngine::GdiplusLoadImage(fgImageName));
	//m_pTextureBrush_bk->SetTransform(
	//	&Gdiplus::Matrix(
	//		10.0 / 64.0, 0.0f, 0.0f,
	//		10.0 / 64.0, 0.0f, 0.0f
	//	)
	//);
	//m_pTextureBrush_fg->SetTransform(
	//	&Gdiplus::Matrix(
	//		10.0 / 64.0, 0.0f, 0.0f,
	//		10.0 / 64.0, 0.0f, 0.0f
	//	)
	//);

	resetDrawInfo_Line();
	resetDrawInfo_Texture();

}

void CLineFlowButtonUI::InitLink(CPaintManagerUI* pManager)
{
	m_pPreLink = static_cast<CLineFlowButtonUI*>(pManager->FindControl(m_sPreLink));
	m_pNextLink = static_cast<CLineFlowButtonUI*>(pManager->FindControl(m_sNextLink));

	if (m_pPreLink == NULL) {
		m_eFlowLinkStatus = FLOW_LINK_START;
	}
	else {
		m_eFlowLinkStatus = FLOW_LINK_END;
	}

}

void CLineFlowButtonUI::ToFlowLine()
{
	m_ePaintType = PaintType_Line;
	m_ePaintMode = PaintMode_Flow;

	resetDrawInfo_Line();

	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::ToFlowTexture()
{
	m_ePaintType = PaintType_Texture;
	m_ePaintMode = PaintMode_Flow;

	resetDrawInfo_Texture();

	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::ToFlowLineSeg()
{
	m_ePaintType = PaintType_Line;
	m_ePaintMode = PaintMode_SegPad;

	resetDrawInfo_Line();

	m_bIsOnce = true;

	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::ToFlickerLine()
{
	m_ePaintType = PaintType_Line;
	m_ePaintMode = PaintMode_Flicker;

	resetDrawInfo_Line();

	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::ToFlickerTexture()
{
	m_ePaintType = PaintType_Texture;
	m_ePaintMode = PaintMode_Flicker;

	resetDrawInfo_Texture();

	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::ToFlickerStaticLine()
{
	m_ePaintType = PaintType_Line;
	m_ePaintMode = PaintMode_Flicker;

	resetDrawInfo_Line();

	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, FLOW_FLICKER_TIMERID_DURATION);
}

void CLineFlowButtonUI::ToFlickerStaticTexture()
{
	m_ePaintType = PaintType_Texture;
	m_ePaintMode = PaintMode_Flicker;

	resetDrawInfo_Texture();

	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, FLOW_FLICKER_TIMERID_DURATION);
}

void CLineFlowButtonUI::ToDrawLine()
{
	m_ePaintType = PaintType_Line;
	m_ePaintMode = PaintMode_SegPad;

	resetDrawInfo_Line();

	m_bIsOnce = false;
	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::ToDrawLineOnce()
{
	m_ePaintType = PaintType_Line;
	m_ePaintMode = PaintMode_SegPad;

	resetDrawInfo_Line();

	m_bIsOnce = true;
	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::ToDrawTextureLine()
{
	m_ePaintType = PaintType_Texture;
	m_ePaintMode = PaintMode_SegPad;

	resetDrawInfo_Texture();

	m_bIsOnce = false;
	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::ToDrawTextureLineOnce()
{
	m_ePaintType = PaintType_Texture;
	m_ePaintMode = PaintMode_SegPad;

	resetDrawInfo_Texture();

	m_bIsOnce = true;
	m_pManager->SetTimer(this, EVENT_ANIMA_FLOW_FLOW_TIMERID, m_nForeAnimaTimerDuration);
}

void CLineFlowButtonUI::PaintLine(HDC hDC)
{
	Gdiplus::Graphics graphics(hDC);
	Gdiplus::Pen      pen(Gdiplus::Color(GetBgLineColor()), GetHeight());
	graphics.DrawLine(&pen, m_rcItem.left, m_rcItem.top + GetHeight() / 2, m_rcItem.left + GetWidth(), m_rcItem.top + GetHeight() / 2);
}

void CLineFlowButtonUI::PaintLine()
{
	PAINTSTRUCT ps = { 0 };
	::BeginPaint(m_pManager->GetPaintWindow(), &ps);

	PaintLine(m_pManager->GetPaintDC());

	::EndPaint(m_pManager->GetPaintWindow(), &ps);
}

INT CLineFlowButtonUI::getPenSize()
{
	switch (m_ePaintDirection) {
	case PaintDiretion_Left2Right:
	case PaintDiretion_Right2Left:
		return GetHeight();
	case PaintDiretion_Bottom2Top:
	case PaintDiretion_Top2Bottom:
		return GetWidth();
	default:
		return 0;
	}
}

void CLineFlowButtonUI::PaintLineFlow(HDC hDC) {
	Gdiplus::Graphics graphics(hDC);

	Gdiplus::Pen	pen(Gdiplus::Color(GetFgLineColor()), getPenSize() - 2);
	Gdiplus::REAL	dp_left_0[] = { 2, 0.1, 1.5, 0.1, 0.8, 0.1 };
	Gdiplus::REAL	dp_left_1[] = { 1.5, 0.1, 0.8, 0.1, 2, 0.1 };
	Gdiplus::REAL	dp_left_2[] = { 0.8, 0.1, 2, 0.1, 1.5, 0.1 };
	Gdiplus::REAL	*dp_left[] = { dp_left_0, dp_left_1, dp_left_2 };

	Gdiplus::REAL	dp_right_0[] = { 2, 0.1, 1.5, 0.1, 0.8, 0.1 };
	Gdiplus::REAL	dp_right_1[] = { 0.8, 0.1, 2, 0.1, 1.5, 0.1 };
	Gdiplus::REAL	dp_right_2[] = { 1.5, 0.1, 0.8, 0.1, 2, 0.1 };
	Gdiplus::REAL	*dp_right[] = { dp_right_0, dp_right_1, dp_right_2 };

	Gdiplus::REAL	dp_up_0[] = { 2, 0.1, 1.5, 0.1, 0.8, 0.1 };
	Gdiplus::REAL	dp_up_1[] = { 1.5, 0.1, 0.8, 0.1, 2, 0.1 };
	Gdiplus::REAL	dp_up_2[] = { 0.8, 0.1, 2, 0.1, 1.5, 0.1 };
	Gdiplus::REAL	*dp_up[] = { dp_up_0, dp_up_1, dp_up_2 };

	Gdiplus::REAL	dp_down_0[] = { 2, 0.1, 1.5, 0.1, 0.8, 0.1 };
	Gdiplus::REAL	dp_down_1[] = { 0.8, 0.1, 2, 0.1, 1.5, 0.1 };
	Gdiplus::REAL	dp_down_2[] = { 1.5, 0.1, 0.8, 0.1, 2, 0.1 };
	Gdiplus::REAL	*dp_down[] = { dp_down_0, dp_down_1, dp_down_2 };

	Gdiplus::REAL* dashArray = NULL;
	switch (m_ePaintDirection) {
	case PaintDiretion_Left2Right:
		dashArray = dp_right[m_nPaintFlowPos];
		break;
	case PaintDiretion_Right2Left:
		dashArray = dp_left[m_nPaintFlowPos];
		break;
	case PaintDiretion_Bottom2Top:
		dashArray = dp_up[m_nPaintFlowPos];
		break;
	case PaintDiretion_Top2Bottom:
		dashArray = dp_down[m_nPaintFlowPos];
		break;
	default:
		dashArray = dp_right[m_nPaintFlowPos];
		break;
	}

	pen.SetDashPattern(dashArray, sizeof(dp_left_0) / sizeof(Gdiplus::REAL));
	pen.SetDashCap(Gdiplus::DashCapRound);
	graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy);

	m_nPaintFlowPos = (++m_nPaintFlowPos) % 3;
}

void CLineFlowButtonUI::PaintGradientFlow(HDC hDC) {

	//	if (m_eFlowLinkStatus == FLOW_LINK_START) {
	//		if (m_nGradientFlowPos == MAX_GRADIENT_LENGTH_INT) {
	//			m_nGradientFlowPos = 0;
	//		}
	//		if (m_pPreLink == NULL || m_pPreLink->m_eFlowLinkStatus == FLOW_LINK_END) {
	//			m_nGradientFlowPos += GetSpeedLength();
	//			if (m_nGradientFlowPos >= MAX_GRADIENT_LENGTH_INT) {
	//				m_nGradientFlowPos = MAX_GRADIENT_LENGTH_INT;
	//				m_eFlowLinkStatus = FLOW_LINK_END;
	//				if (m_pNextLink != NULL) {
	//					m_pNextLink->m_eFlowLinkStatus = FLOW_LINK_START;
	//				}
	//				else {
	//					m_eFlowLinkStatus = FLOW_LINK_START;
	//				}
	//			}
	//		}
	//	}
	m_nGradientFlowPos += GetSpeedLength();
	if (m_nGradientFlowPos >= MAX_GRADIENT_LENGTH_INT) {
		m_nGradientFlowPos = 0;
	}

	//m_nGradientFlowPos = (m_nGradientFlowPos + GetSpeedLength()) % 100;
	//GradientFgPaint(hDC, FLOAT(m_nGradientFlowPos) / MAX_GRADIENT_LENGTH_FLOAT);
	FLOAT  mid = FLOAT(m_nGradientFlowPos) / MAX_GRADIENT_LENGTH_FLOAT;
	GradientFgPaint_1(hDC, mid);
}

void CLineFlowButtonUI::PaintFlowWithTexture(HDC hDC)
{
	Gdiplus::Graphics graphics(hDC);
	graphics.FillRectangle(m_pTextureBrush_fg, GetPos().left, GetPos().top, GetWidth(), GetHeight());
}

void CLineFlowButtonUI::PaintLineFlicker(HDC hDC) {
	static BOOL bFGImage = FALSE;
	static DWORD lastFlickerTime = 0;

	Gdiplus::Graphics graphics(hDC);

	if (bFGImage) {
		Gdiplus::Pen      pen(Gdiplus::Color(GetFgLineColor()), getPenSize());
		graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy);
	}
	else {
		Gdiplus::Pen      pen(Gdiplus::Color(GetBgLineColor()), getPenSize());
		graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy);
	}

	DWORD now = GetTickCount();
	if (now - lastFlickerTime > FLOW_FLICKER_TIMERID_DURATION) {
		bFGImage = !bFGImage;
		lastFlickerTime = now;
	}
}

void CLineFlowButtonUI::PaintLineSeg(HDC hDC) {
	Gdiplus::Graphics graphics(hDC);
	Gdiplus::Pen      pen(Gdiplus::Color(GetFgLineColor()), getPenSize() - 2);
	pen.SetStartCap(Gdiplus::LineCapRound);
	pen.SetEndCap(Gdiplus::LineCapRound);
	graphics.DrawLine(&pen, m_startx, m_starty, m_endx, m_endy);
}

void CLineFlowButtonUI::PaintLineSeg() {
	PAINTSTRUCT ps = { 0 };
	::BeginPaint(m_pManager->GetPaintWindow(), &ps);

	PaintLineSeg(m_pManager->GetPaintDC());

	::EndPaint(m_pManager->GetPaintWindow(), &ps);
}

void CLineFlowButtonUI::PaintFlickerWithTexture(HDC hDC)
{
	static BOOL bFGImage = FALSE;
	static DWORD lastFlickerTime = 0;

	Gdiplus::Graphics graphics(hDC);

	if (bFGImage) {
		graphics.FillRectangle(m_pTextureBrush_fg, m_X, m_Y, m_width, m_height);
	}
	else {
		graphics.FillRectangle(m_pTextureBrush_bk, m_X, m_Y, m_width, m_height);
	}

	DWORD now = GetTickCount();
	if (now - lastFlickerTime > FLOW_FLICKER_TIMERID_DURATION) {
		bFGImage = !bFGImage;
		lastFlickerTime = now;
	}
}

void CLineFlowButtonUI::PaintWithTexture(HDC hDC)
{
	Gdiplus::Graphics graphics(hDC);

	graphics.FillRectangle(m_pTextureBrush_bk, GetPos().left, GetPos().top, GetWidth(), GetHeight());
}

void CLineFlowButtonUI::PaintWithTexture()
{
	PAINTSTRUCT ps = { 0 };
	::BeginPaint(m_pManager->GetPaintWindow(), &ps);

	PaintWithTexture(m_pManager->GetPaintDC());

	::EndPaint(m_pManager->GetPaintWindow(), &ps);
}

void CLineFlowButtonUI::PaintLineSegWithTexture(HDC hDC)
{
	Gdiplus::Graphics graphics(hDC);

	graphics.FillRectangle(m_pTextureBrush_bk, m_X, m_Y, m_width, m_height);
}

void CLineFlowButtonUI::PaintLineSegWithTexture()
{
	PAINTSTRUCT ps = { 0 };
	::BeginPaint(m_pManager->GetPaintWindow(), &ps);

	PaintLineSegWithTexture(m_pManager->GetPaintDC());

	::EndPaint(m_pManager->GetPaintWindow(), &ps);
}


void CLineFlowButtonUI::updateDrawInfo_Line()
{
	switch (m_ePaintDirection) {
	case  PaintDiretion_Left2Right:
		m_endx += m_nDrawSpeed;
		if (m_endx > m_rcItem.right) {
			m_endx = m_rcItem.right;
		}

		if (m_endx == m_rcItem.left + GetWidth()) {
			if (!m_bIsOnce) {
				resetDrawInfo_Line();
			}
			ShowComplete();
		}
		break;

	case  PaintDiretion_Right2Left:
		m_endx -= m_nDrawSpeed;
		if (m_endx < m_rcItem.left) {
			m_endx = m_rcItem.left;
		}

		if (m_endx == m_rcItem.left) {
			if (!m_bIsOnce) {
				resetDrawInfo_Line();
			}
			ShowComplete();
		}
		break;

	case  PaintDiretion_Bottom2Top:
		m_endy -= m_nDrawSpeed;
		if (m_endy < m_rcItem.top) {
			m_endy = m_rcItem.top;
		}

		if (m_endy == m_rcItem.top) {
			if (!m_bIsOnce) {
				resetDrawInfo_Line();
			}
			ShowComplete();
		}
		break;

	case  PaintDiretion_Top2Bottom:
		m_endy += m_nDrawSpeed;
		if (m_endy > m_rcItem.bottom) {
			m_endy = m_rcItem.bottom;
		}

		if (m_endy == m_rcItem.bottom) {
			if (!m_bIsOnce) {
				resetDrawInfo_Line();
			}
			ShowComplete();
		}
		break;
	}
}

void CLineFlowButtonUI::updateDrawInfo_Texture()
{
	switch (m_ePaintDirection) {
	case  PaintDiretion_Left2Right:
		m_width += m_nDrawSpeed;
		if (m_width > GetWidth()) {
			m_width = GetWidth();
		}
		if (m_width == GetWidth()) {
			if (!m_bIsOnce) {
				resetDrawInfo_Texture();
			}
			ShowComplete();
		}
		break;

	case  PaintDiretion_Right2Left:
		m_X -= m_nDrawSpeed;
		m_width += m_nDrawSpeed;
		if (m_width > GetWidth()) {
			m_width = GetWidth();
		}
		if (m_width == GetWidth()) {
			if (!m_bIsOnce) {
				resetDrawInfo_Texture();
			}
			ShowComplete();
		}
		break;

	case  PaintDiretion_Bottom2Top:
		m_Y -= m_nDrawSpeed;
		m_height += m_nDrawSpeed;
		if (m_height > GetHeight()) {
			m_height = GetHeight();
		}
		if (m_height == GetHeight()) {
			if (!m_bIsOnce) {
				resetDrawInfo_Texture();
			}
			ShowComplete();
		}
		break;

	case  PaintDiretion_Top2Bottom:
		m_height += m_nDrawSpeed;
		if (m_height > GetHeight()) {
			m_height = GetHeight();
		}
		if (m_height == GetHeight()) {
			if (!m_bIsOnce) {
				resetDrawInfo_Texture();
			}
			ShowComplete();
		}
		break;

	}
}

void CLineFlowButtonUI::resetDrawInfo_Line()
{
	switch (m_ePaintDirection) {
	case  PaintDiretion_Left2Right:
		m_startx = m_rcItem.left;
		m_starty = m_rcItem.top + GetHeight() / 2;
		m_endx = m_rcItem.left + m_nDrawSpeed;
		m_endy = m_rcItem.top + GetHeight() / 2;
		break;

	case  PaintDiretion_Right2Left:
		m_startx = m_rcItem.right;
		m_starty = m_rcItem.top + GetHeight() / 2;
		m_endx = m_rcItem.right + m_nDrawSpeed;
		m_endy = m_rcItem.top + GetHeight() / 2;
		break;

	case  PaintDiretion_Bottom2Top:
		m_startx = m_rcItem.left + GetWidth() / 2;
		m_starty = m_rcItem.bottom;
		m_endx = m_rcItem.left + GetWidth() / 2;
		m_endy = m_rcItem.bottom - m_nDrawSpeed;
		break;

	case  PaintDiretion_Top2Bottom:
		m_startx = m_rcItem.left + GetWidth() / 2;
		m_starty = m_rcItem.top;
		m_endx = m_rcItem.left + GetWidth() / 2;
		m_endy = m_rcItem.top + m_nDrawSpeed;
		break;

	}
}

void CLineFlowButtonUI::resetDrawInfo_Texture()
{
	switch (m_ePaintDirection) {
	case  PaintDiretion_Left2Right:
		m_X = m_rcItem.left;
		m_Y = m_rcItem.top;
		m_width = m_nDrawSpeed;
		m_height = GetHeight();
		break;

	case  PaintDiretion_Right2Left:
		m_X = m_rcItem.right - m_nDrawSpeed;
		m_Y = m_rcItem.top;
		m_width = m_nDrawSpeed;
		m_height = GetHeight();
		break;

	case  PaintDiretion_Bottom2Top:
		m_X = m_rcItem.left;
		m_Y = m_rcItem.bottom - m_nDrawSpeed;
		m_width = GetWidth();
		m_height = m_nDrawSpeed;
		break;

	case  PaintDiretion_Top2Bottom:
		m_X = m_rcItem.left;
		m_Y = m_rcItem.top;
		m_width = GetWidth();
		m_height = m_nDrawSpeed;
		break;

	}
}

